#include "req.h"
#include "../utils/log.h"
#include "landload.h"
#include "sys/socket.h"

/**
 * @brief 请求游戏状态
 * request:
 * {
       "user_id": number,
       "game_id": number,
       "username": string
    }
 */
void getGameStatus(even_detail *event, http_request_t *request) {
    cJSON *body = request->body;
    if (body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // 获取用户名
    cJSON *username = cJSON_GetObjectItem(body, "username");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    if (username == NULL || user_id == NULL || game_id == NULL) {
        sendBadRequest(event, request);
        return;
    }

    // 获取游戏对象
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) {
        sendBadRequest(event, request);
        return;
    }

    player_t *player = NULL;
    pthread_mutex_lock(&game->mutex);
    for (int i = 0; i < 3; i++) {
        if (game->players[i].id == user_id->valueint) {
            player = &game->players[i];
            break;
        }
    }
    if (player == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // log_info("gmae to json");
    cJSON *data = game_to_json(game);
    // 添加用户手牌
    cJSON *handcard = cJSON_CreateArray();

    for (int i = 0; i < player->handcard.len; i++) {
        cJSON_AddItemToArray(handcard,
                             cJSON_CreateNumber(player->handcard.data[i]));
    }
    pthread_mutex_unlock(&game->mutex);
    // log_info("handcard");
    cJSON_AddItemToObject(data, "handcard", handcard);
    // log_info("add success");
    cJSON *resp = http_create_response(RESPONSE_OK, "success", data);
    // log_info("send");
    char *message = cJSON_Print(resp);
    send(event->fd, message, strlen(message), 0);
    free(message);
    cJSON_Delete(resp);
    return;
}

/**
 * @brief 请求出牌
 * request:
 * {
       "user_id": number,
       "game_id": number,
       "username": string,
       "card": [number]
    }
    response:
    {
        "game_end": bool
    }
 */
void getOutCard(even_detail *event, http_request_t *request) {
    cJSON *body = request->body;
    if (body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // 获取用户名
    cJSON *username = cJSON_GetObjectItem(body, "username");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    if (username == NULL || user_id == NULL || game_id == NULL) {
        log_info("getOutCard: parse fail");
        sendBadRequest(event, request);
        return;
    }

    // 获取游戏对象
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) {
        log_info("getOutCard: game not exist");
        sendBadRequest(event, request);
        return;
    }
    Vec(CARD) cards;
    vec_init(&cards, 0, 10);
    cJSON *card = cJSON_GetObjectItem(body, "cards");
    if (card == NULL) {
        log_info("getOutCard: parse cards fail");
        sendBadRequest(event, request);
        return;
    }
    for (int i = 0; i < cJSON_GetArraySize(card); i++) {
        cJSON *card_json = cJSON_GetArrayItem(card, i);
        vec_append(&cards, card_json->valueint);
    }

    player_t *player = &game->players[game->who];

    if (game->status != GAME_STATUS_GAMEING ||
        player->id != user_id->valueint) {
        log_info("getOutCard: game not start or not your turn");
        sendBadRequest(event, request);
        return;
    }

    char *msg = game_play_card(game, player, cards.data, cards.len);
    cJSON *resp;
    cJSON *data = cJSON_CreateObject();
    if (msg == NULL) {
        // 判断是否结束游戏
        cJSON_AddBoolToObject(data, "game_end", player->handcard.len == 0);
        resp = http_create_response(RESPONSE_OK, "success", data);
        if (player->handcard.len == 0) {
            game->status = GAME_STATUS_END;
            // 唤醒游戏线程
            pthread_cond_signal(&game->cond);
        }
        char *json = cJSON_Print(resp);
        send(event->fd, json, strlen(json), 0);
        free(json);
        vec_free(&cards);
        cJSON_Delete(resp);
        return;
    }
    cJSON_AddBoolToObject(data, "game_end", false);
    resp = http_create_response(RESPONSE_BAD_REQUEST, msg, data);
    char *json = cJSON_Print(resp);
    send(event->fd, json, strlen(json), 0);
    free(json);
    vec_free(&cards);
    cJSON_Delete(resp);
    return;
}

/**
 * @brief 请求抢地主
 * request：
 * request:
 * {
       "user_id": number,
       "game_id": number,
       "username": string,
       "status": number,
    }
    response：
    {
        code：
        message：
    }
 */
void getRobot(even_detail *event, http_request_t *request) {
    // 解析json
    cJSON *body = request->body;
    log_info("%s", cJSON_Print(body));
    if (body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // 获取用户名
    cJSON *username = cJSON_GetObjectItem(body, "username");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    cJSON *status = cJSON_GetObjectItem(body, "status");
    log_info("user_id:%d", user_id->valueint);
    if (username == NULL || user_id == NULL || game_id == NULL ||
        status == NULL) {
        sendBadRequest(event, request);
        return;
    }

    // 获取游戏对象
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) {
        sendBadRequest(event, request);
        return;
    }

    player_t *player = &game->players[game->who];

    if ((game->status != GAME_STATUS_ROBLOAD &&
         game->status != GAME_STATUS_CALLLOAD) ||
        player->id != user_id->valueint) {
        sendBadRequest(event, request);
        return;
    }

    pthread_mutex_lock(&game->mutex);
    for (int i = 0; i < 3; i++) {
        if (game->players[i].id == user_id->valueint) {
            game->rob_status[i] = status->valueint;
        }
    }
    pthread_mutex_unlock(&game->mutex);
    // 唤醒游戏线程
    pthread_cond_signal(&game->cond);

    cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
    char *json = cJSON_Print(resp);
    send(event->fd, json, strlen(json), 0);
    free(json);
    cJSON_Delete(resp);
    return;
}

/**
 * @brief 加入游戏
 * requeset:
 * {
        "user_id": number,
        "username": string,
        "game_id": number
    }
 */
void join_room(even_detail *event, http_request_t *request) {
    if (request->body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    cJSON *body = request->body;
    cJSON *player_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    cJSON *username = cJSON_GetObjectItem(body, "username");
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) { // 游戏不存在
        sendBadRequest(event, request);
        return;
    }
    pthread_mutex_lock(&game->mutex);
    if (game->status != GAME_STATUS_WAIT_PLAYER || game->player_count == 3) {
        sendBadRequest(event, request);
        return;
    }

    for (int i = 0; i < 3; i++) {
        if (game->players[i].id < 0) {
            game->players[i].id = player_id->valueint;
            game->players[i].status = PLAYER_STATUS_NONE;
            game->players[i].username = strdup(username->valuestring);
            game->player_count++;
            log_info("player %d join the game", player_id->valueint);
            pthread_mutex_unlock(&game->mutex);

            cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
            char *message = cJSON_Print(resp);
            send(event->fd, message, strlen(message), 0);
            free(message);
            cJSON_Delete(resp);
            return;
        }
    }
    pthread_mutex_unlock(&game->mutex);
    sendBadRequest(event, request);
    return;
}

/**
 * @brief 创建房间
 * request:
 * {
        "user_id": number,
        "room_name": string
 }
 */
void create_room(even_detail *event, http_request_t *request) {
    if (request->body == NULL) {
        sendBadRequest(event, request);
        return;
    }

    cJSON *body = request->body;
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *room_name = cJSON_GetObjectItem(body, "room_name");
    cJSON *username = cJSON_GetObjectItem(body, "username");
    if (room_name == NULL || user_id == NULL || username == NULL) {
        log_info("parse fail");
        sendBadRequest(event, request);
        return;
    }
    game_node_t *game_node = (game_node_t *)malloc(sizeof(game_node_t));
    game_t *game = game_init(user_id->valueint, room_name->valuestring);
    game_node->game = game;
    player_t *player = &game_node->game->players[0];
    game->player_count = 1;
    player->id = user_id->valueint;
    player->username = strdup(username->valuestring);
    player->status = PLAYER_STATUS_NONE;
    game_node->game = game;
    landload_add_game(game_node);
    cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
    char *message = cJSON_Print(resp);
    send(event->fd, message, strlen(message), 0);
    free(message);
    cJSON_Delete(resp);
    // 开启game线程
    pthread_t game_thread;
    pthread_create(&game_thread, NULL, game_thread_func, game);
    game_node->thread = game_thread;
    return;
}

/**
 * @brief 退出游戏
 * request:
 * {
        "game_id": number,
        "user_id": number
    }
 */
void quit_game(even_detail *event, http_request_t *request) {
    if (request->body == NULL) {
        sendBadRequest(event, request);
        return;
    }

    cJSON *body = request->body;
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");

    game_node_t *game_node = landload_get_game_node(game_id->valueint);
    game_t *game = game_node->game;

    pthread_mutex_lock(&game->mutex);
    game->status = GAME_STATUS_END;
    game->player_count--;

    for (int i = 0; i < 3; i++) {
        if (game->players[i].id = user_id) {
            game->players[i].id = -1;
        }
    }
    if (game->player_count == 0) {
        landload_remove_game(game_node);
        // 关闭游戏线程
        pthread_cancel(game_node->thread);
        log_info("game thread exit");
        game_destory(game);
    } else {
        pthread_mutex_unlock(&game->mutex);
        // 唤醒游戏线程
        pthread_cond_signal(&game->cond);
    }

    cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
    char *message = cJSON_Print(resp);
    send(event->fd, message, strlen(message), 0);
    free(message);
    cJSON_Delete(resp);
    return;
}

/**
 * @brief 获取房间列表
 * request: {
 *        "user_id": number,
 *          "username": string,
 *          "game_id": number
 *
 * }
 * responese: {
 *       "code": number,
 *        "message": string,
 *        "data": [
 *                   {
 *                       "game_id": number,
 *                       "player_count": number,
 *                       "status": number,
 *                       "room_name": string
 *                   }
 *               ]
 * }
 */
void get_room_list(even_detail *event, http_request_t *request) {
    cJSON *json_array = cJSON_CreateArray();

    game_node_t *game_node;
    list_for_each_entry(game_node, &landload->game_list.list, list) {
        cJSON *game_node_json = cJSON_CreateObject();
        cJSON_AddNumberToObject(game_node_json, "game_id",
                                (game_node->game->id));
        cJSON_AddNumberToObject(game_node_json, "player_count",
                                (game_node->game->player_count));
        cJSON_AddNumberToObject(game_node_json, "status",
                                (game_node->game->status));
        cJSON_AddStringToObject(game_node_json, "room_name",
                                (game_node->game->room_name));
        cJSON_AddItemToArray(json_array, game_node_json);
    }
    cJSON *root = http_create_response(RESPONSE_OK, "success", json_array);
    char *message = cJSON_Print(root);
    send(event->fd, message, strlen(message), 0);
    free(message);
    cJSON_Delete(root);
    return;
}

/**
 * @brief 请求修改玩家状态
 * request：
 * request:
 * {
       "user_id": number,
       "game_id": number,
       "username": string,
       "status": number,
    }
    response：
    {
        code：
        message：
    }
 */
void setStatus(even_detail *event, http_request_t *request) {
    // 解析json
    cJSON *body = request->body;
    if (body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // 获取游戏对象
    // 获取用户名
    cJSON *username = cJSON_GetObjectItem(body, "username");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    cJSON *status = cJSON_GetObjectItem(body, "status");
    if (username == NULL || user_id == NULL || game_id == NULL ||
        status == NULL) {
        sendBadRequest(event, request);
        return;
    }

    // 获取游戏对象
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) {
        sendBadRequest(event, request);
        return;
    }

    if (game->status != GAME_STATUS_WAIT_PLAYER) {
        sendBadRequest(event, request);
        return;
    }

    pthread_mutex_lock(&game->mutex);
    for (int i = 0; i < 3; i++) {
        if (game->players[i].id == user_id->valueint) {
            game->players[i].status = status->valueint;
            pthread_mutex_unlock(&game->mutex);
            // 唤醒游戏线程
            pthread_cond_signal(&game->cond);
            log_info("set status success");
            // 返回成功
            cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
            char *json = cJSON_Print(resp);
            send(event->fd, json, strlen(json), 0);
            free(json);
            cJSON_Delete(resp);
            return;
        }
    }
    pthread_mutex_unlock(&game->mutex);
    
    sendBadRequest(event, request);
    return;
}

void outCardPass(even_detail *event, http_request_t *request) {
    cJSON *body = request->body;
    if (body == NULL) {
        sendBadRequest(event, request);
        return;
    }
    // 获取用户名
    cJSON *username = cJSON_GetObjectItem(body, "username");
    cJSON *user_id = cJSON_GetObjectItem(body, "user_id");
    cJSON *game_id = cJSON_GetObjectItem(body, "game_id");
    if (username == NULL || user_id == NULL || game_id == NULL) {
        log_info("getOutCard: parse fail");
        sendBadRequest(event, request);
        return;
    }

    // 获取游戏对象
    game_t *game = landload_get_game(game_id->valueint);
    if (game == NULL) {
        log_info("getOutCard: game not exist");
        sendBadRequest(event, request);
        return;
    }

    if (game->last_who == game->who) {
        log_info("first out card cant not pass");
        sendBadRequest(event, request);
        return;
    }

    player_t *player = &game->players[game->who];

    if (game->status != GAME_STATUS_GAMEING ||
        player->id != user_id->valueint) {
        log_info("getOutCard: game not start or not your turn");
        sendBadRequest(event, request);
        return;
    }
    // 跳过
    pthread_mutex_lock(&game->mutex);
    game->who = (game->who + 1) % 3;
    pthread_mutex_unlock(&game->mutex);

    cJSON *resp = http_create_response(RESPONSE_OK, "success", NULL);
    char *json = cJSON_Print(resp);
    send(event->fd, json, strlen(json), 0);
    free(json);
    cJSON_Delete(resp);
    return;
}